﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Convertor.Interface;
using Wpf.CommonTools.Converter;
using Wpf.CommonTools.SystemExtension;
using Wpf.CommonTools.StringExtension;
using Wpf.CommonTools.EnumExtension;

namespace Convertor.Plugin.InputAndOutput
{
    [Flags]
    public enum OperateInputTypes
    {
        SetAs = 1,
        CombineWithOutput = 2,
        ReplaceWithOutput = 4,
        RevertWithOutput = 8,
        CompareToOutput = 16,
        PushToMemory = 32,
        PopFromMemory = 64
    }

    [Flags]
    public enum OperateOutputTypes
    {
        SetAs = 1,
        CombineWithInput = 2,
        ReplaceWithInput = 4,
        RevertWithInput = 8,
        CompareToInput = 16,
        PushToMemory = 32,
        PopFromMemory = 64
    }

    [Flags]
    public enum CompareTypes
    {
        IsEqual = 1,
        IsNotEqual = 2,
        Great = 4,
        Less = 8
    }

    [Serializable]
    public class ConfigContent : IConfigContent, ISerializable, ICloneable, INotifyPropertyChanged
    {
        private OutputTypes operateTarget = OutputTypes.OutputContent;

        public OutputTypes OperateTarget
        {
            get { return operateTarget; }
            set
            {
                operateTarget = value;
                if (PropertyChanged != null)
                {
                    PropertyChanged(this, new PropertyChangedEventArgs("OperateType"));
                    PropertyChanged(this, new PropertyChangedEventArgs("ToolTip"));
                }
            }
        }
        private EnumModel operateType;

        public EnumModel OperateType
        {
            get { return operateType ?? (operateType = new EnumModel() { Name = UILanguage.TryFindResource("Plugin_InputAndOutput_OperateType_" + OperateOutputTypes.SetAs), Value = 1 }); }
            set { operateType = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("ToolTip")); } }
        }
        private string operateText;

        public string OperateText
        {
            get { return operateText; }
            set { operateText = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("ToolTip")); } }
        }
        private string replaceText;

        public string ReplaceText
        {
            get { return replaceText; }
            set { replaceText = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("ToolTip")); } }
        }
        private string uniqName = Guid.NewGuid().ToString("N");

        public string UniqName
        {
            get { return uniqName ?? (uniqName = Guid.NewGuid().ToString("N")); }
            set { uniqName = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("ToolTip")); } }
        }
        private CompareTypes compareType = CompareTypes.IsEqual;

        public CompareTypes CompareType
        {
            get { return compareType; }
            set { compareType = value; if (PropertyChanged != null) { PropertyChanged(this, new PropertyChangedEventArgs("ToolTip")); } }
        }

        public ConfigContent()
        {
        }

        public override string ToString()
        {
            return ToolTip;
        }

        #region IToolTip 成员

        public string ToolTip
        {
            get
            {
                string a;
                switch (OperateType.Value)
                {
                    case 1:
                        a = string.Format(UILanguage.TryFindResource("Plugin_InputAndOutput_Info_SetAs"),
                            UILanguage.TryFindResource(operateTarget.ToString()),
                            this.replaceText.ToLimitLength(100));
                        break;
                    case 2:
                        a = string.Format(UILanguage.TryFindResource("Plugin_InputAndOutput_Info_Combine"),
                            UILanguage.TryFindResource(operateTarget.ToString()),
                            UILanguage.TryFindResource("Plugin_InputAndOutput_OperateType_" + operateType.Name),
                            this.operateText.ToLimitLength(100));
                        break;
                    case 16:
                        var b = this.compareType.GetFlags().Select(p => UILanguage.TryFindResource("Plugin_InputAndOutput_CompareTypes_" + p)).Aggregate((k, n) => k + UILanguage.TryFindResource("Or") + n);
                        a = string.Format(UILanguage.TryFindResource("Plugin_InputAndOutput_Info_Compare"),
                            UILanguage.TryFindResource(operateTarget.ToString()),
                            UILanguage.TryFindResource("Plugin_InputAndOutput_OperateType_" + operateType.Name),
                            b,
                            UILanguage.TryFindResource(operateTarget == OutputTypes.InputContent ? OutputTypes.OutputContent.ToString() : OutputTypes.InputContent.ToString()));
                        break;
                    case 32:
                    case 64:
                        a = string.Format(UILanguage.TryFindResource("Plugin_InputAndOutput_Info_Memory"),
                            UILanguage.TryFindResource(operateTarget.ToString()),
                            UILanguage.TryFindResource("Plugin_InputAndOutput_OperateType_" + operateType.Name),
                            this.uniqName);
                        break;
                    default:
                        a = string.Format(UILanguage.TryFindResource("Plugin_InputAndOutput_Info_Default"),
                            UILanguage.TryFindResource(operateTarget.ToString()),
                            UILanguage.TryFindResource("Plugin_InputAndOutput_OperateType_" + operateType.Name));
                        break;
                }
                return a = a.Substring(0, 1).ToUpper() + a.Substring(1).ToLower();
            }
        }

        #endregion

        #region ISerializable 成员

        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue("OperateType", OperateType, typeof(EnumModel));
            info.AddValue("OperateText", OperateText, typeof(string));
            info.AddValue("UniqName", UniqName, typeof(string));
            info.AddValue("ReplaceText", ReplaceText, typeof(string));
            info.AddValue("CompareType", CompareType, typeof(CompareTypes));
            info.AddValue("OperateTarget", OperateTarget, typeof(OutputTypes));
        }

        public ConfigContent(SerializationInfo info, StreamingContext context)
        {
            try
            {
                OperateType = (EnumModel)info.GetValue("OperateType", typeof(EnumModel));
            }
            catch { }
            try
            {
                OperateText = (string)info.GetValue("OperateText", typeof(string));
            }
            catch { }
            try
            {
                ReplaceText = (string)info.GetValue("ReplaceText", typeof(string));
            }
            catch { }
            try
            {
                UniqName = (string)info.GetValue("UniqName", typeof(string));
            }
            catch { }
            try
            {
                CompareType = (CompareTypes)info.GetValue("CompareType", typeof(CompareTypes));
            }
            catch { }
            try
            {
                OperateTarget = (OutputTypes)info.GetValue("OperateTarget", typeof(OutputTypes));
            }
            catch { }
        }

        #endregion

        #region ICloneable 成员

        public object Clone()
        {
            ConfigContent a = new ConfigContent()
            {
                OperateType = this.OperateType,
                OperateText = this.OperateText,
                ReplaceText = this.ReplaceText,
                UniqName = this.UniqName,
                OperateTarget = this.OperateTarget,
                CompareType = this.CompareType
            };
            return a;
        }

        #endregion

        #region INotifyPropertyChanged 成员

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

    }
}
